﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;

namespace frag_boardgame
{

    [Flags]
    public enum SquareWalls
    {
        None = 0,
        Up = 1,
        Down = 2,
        Left = 4,
        Right = 8
    }
    
    /// <summary>
    /// This class is handling the Square unit
    /// </summary>
    [DataContract]
    public class Square : IBounds
    {
        [DataMember]
        private Player _player;

        [DataMember]
        private SquareWalls walls; //TODO: refactoring : change to Directions (but need to change the enum)

        [DataMember]
        private int x;

        [DataMember]
        private int y;

        /// <summary>
        /// Constructor
        /// </summary>
        public Square(int row,int column)
        {
            _player = null; // currently there is no player on this square

            x = row;
            y = column;

            walls = SquareWalls.None;
        }

        // player property
        public Player player
        {
            get
            {
                return _player;
            }
            set
            {
                _player = value;
            }
        }

        public int Row
        {
            get
            {
                return x;
            }
        }

        public int Column
        {
            get
            {
                return y;
            }
        }

        public SquareWalls Walls
        {
            set
            {
                walls = value;
            }
            get
            {
                return walls;
            }
        }


        // override object.Equals
        public override bool Equals(object obj)
        {
            Square s = obj as Square;
            if (s == null) return false;

            return Equals(s.x, x) && 
                Equals(s.y, y) &&
                Equals(s.player, player);
        }

        // override object.GetHashCode
        public override int GetHashCode()
        {
            return x.GetHashCode() ^ y.GetHashCode() ^ ((player == null) ? 0 : player.GetHashCode());
        }


        #region ISerializable Members

        public void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            info.AddValue("Row", x);
            info.AddValue("Column", y);
            info.AddValue("Player", player);
        }

        protected Square(SerializationInfo info, StreamingContext context)
        {
            x = (int)info.GetValue("Row", typeof(int));
            y = (int)info.GetValue("Column", typeof(int));
            player = (Player)info.GetValue("Player", typeof(Player));
        }

        #endregion

        #region Walls properties

        public bool HasWall(SquareWalls wall)
        {
            return ((walls & wall) == wall);
        }
        public void AddWall(SquareWalls wall)
        {
            walls = walls | wall;
        }
        public void RemoveWall(SquareWalls wall)
        {
            if (HasWall(wall))
                walls = walls ^ wall;
        }
        public float calculateVerticalDistance(Square sqr)
        {
            return this.Row - sqr.Row;
        }
        public float calculateHorizontalDistance(Square sqr)
        {
            return this.Column - sqr.Column;
        }

        public float calculateDistance(Square sqr)
        {
            float width = calculateHorizontalDistance(sqr);
            float height = calculateVerticalDistance(sqr);
            return (float) Math.Sqrt(height * height + width * width);
        }
        #endregion
    
        #region IBounds Members

        public bool IsCrossing(Line line)
        {
            foreach (Line boundLine in GetBound())
            {
                if (Line.AreCrossing(line,boundLine))
                    return true;
            }
            return false;
        }

        public ICollection<Line> GetBound()
        {
            List<Line> lines = new List<Line>();
            
            if (HasWall(SquareWalls.Down))
                lines.Add(new Line(y, x, y + 1, x));
            
            if (HasWall(SquareWalls.Up))
                lines.Add(new Line(y, x+1, y + 1, x+1));
            
            if (HasWall(SquareWalls.Left))
                lines.Add(new Line(y, x, y, x+1));
            
            if (HasWall(SquareWalls.Right))
                lines.Add(new Line(y+1, x, y + 1, x+1));
            
            return lines;
        
        }

        #endregion
    }
}
